namespace Org.Loon.Framework.Xna.Game.Action.Scripting.Pack
{

    using Org.Loon.Framework.Xna.Game.Core.Timer;
    using Org.Loon.Framework.Xna.Game.Action.Sprite;

    public abstract class PackView
    {
        
	public class CameraView : PackView {

		private static CameraView instance;

		public static CameraView GetInstance(object o, int w, int h) {
			if (instance == null) {
				instance = new CameraView(o, w, h);
			} else if (instance.obj != o || instance.width != w
					|| instance.height != h) {
				instance = new CameraView(o, w, h);
			}
			return instance;
		}

		private LTimer timer = new LTimer(150);

		private float cameraX, cameraY;

		private float width, height;

		private Bind bind;

		private object obj;

		public CameraView(object o, int w, int h) {
			this.width = w;
			this.height = h;
			this.Bind(o);
		}

		public void SetDelay(long d) {
			timer.SetDelay(d);
		}

		public long GetDelay() {
			return timer.GetDelay();
		}

		public override float WorldToRealX(float x) {
			return x - cameraX + width / 2;
		}

        public override float WorldToRealY(float y)
        {
			return y - cameraY + height / 2;
		}

        public override float RealToWorldX(float x)
        {
			return x + cameraX - width / 2;
		}

        public override float RealToWorldY(float y)
        {
			return y + cameraY - height / 2;
		}

		public void Bind(object o) {
			this.obj = o;
			if (o == null) {
				bind = null;
			} else {
				bind = new Bind(o);
			}
		}

        public override void Update(long elapsedTime)
        {
			if (bind == null) {
				return;
			}
			if (timer.Action(elapsedTime)) {
				float dx = bind.GetX() - cameraX;
				float cx = width / 3;
				if (dx > cx) {
					cameraX += dx - cx;
				}
				if (dx < -cx) {
					cameraX += dx + cx;
				}
				float dy = bind.GetY() - cameraY;
				float cy = height / 3;
				if (dy > cy) {
					cameraY += dy - cy;
				}
				if (dy < -cy) {
					cameraY += dy + cy;
				}
			}
		}

		public void Reset() {
			cameraX = width / 2;
			cameraY = height / 2;
			Update(0);
		}
	}

	public class EmptyView : PackView {

		private static EmptyView instance;

		public static EmptyView GetInstance() {
			if (instance == null) {
				instance = new EmptyView();
			}
			return instance;
		}

		public EmptyView() {
		}

        public override float WorldToRealX(float x)
        {
			return x;
		}

        public override float WorldToRealY(float y)
        {
			return y;
		}

        public override float RealToWorldX(float x)
        {
			return x;
		}

        public override float RealToWorldY(float y)
        {
			return y;
		}

        public override void Update(long elapsedTime)
        {

		}
	}

	public abstract float WorldToRealX(float x);

	public abstract float WorldToRealY(float y);

	public abstract float RealToWorldX(float x);

	public abstract float RealToWorldY(float y);

	public abstract void Update(long elapsedTime);
    }
}
